#include <windows.h>
#include <windowsx.h>
#include <string>
#include "app.h"

static App* g_app{};

LRESULT CALLBACK WndProc(HWND h, UINT m, WPARAM w, LPARAM l){
    switch(m){
    case WM_CREATE: return 0;
    case WM_SIZE: if(g_app) g_app->on_size(LOWORD(l), HIWORD(l)); return 0;
    case WM_KEYDOWN: if(g_app) g_app->on_key(w); return 0;
    case WM_MOUSEWHEEL: if(g_app) g_app->on_wheel(GET_WHEEL_DELTA_WPARAM(w), GET_X_LPARAM(l), GET_Y_LPARAM(l)); return 0;
    case WM_LBUTTONDOWN: if(g_app) g_app->on_mouse_down(GET_X_LPARAM(l), GET_Y_LPARAM(l)); return 0;
    case WM_MOUSEMOVE: if(g_app) g_app->on_mouse_move(GET_X_LPARAM(l), GET_Y_LPARAM(l), w); return 0;
    case WM_LBUTTONUP: ReleaseCapture(); return 0;
    case WM_DESTROY: PostQuitMessage(0); return 0;
    }
    return DefWindowProcW(h,m,w,l);
}

int APIENTRY WinMain(HINSTANCE inst,HINSTANCE,LPSTR, int show){
    const wchar_t* cls=L"ThreeBodyWnd";
    WNDCLASSW wc{}; wc.style=CS_HREDRAW|CS_VREDRAW; wc.lpfnWndProc=WndProc; wc.hInstance=inst; wc.hCursor=LoadCursor(nullptr,IDC_ARROW); wc.hbrBackground=(HBRUSH)(COLOR_WINDOW+1); wc.lpszClassName=cls; RegisterClassW(&wc);
    int W=1280,H=720; HWND hwnd=CreateWindowExW(0,cls,L"Three Body",WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,W,H,nullptr,nullptr,inst,nullptr); ShowWindow(hwnd,show); UpdateWindow(hwnd);

    App app; g_app=&app; RECT rc; GetClientRect(hwnd,&rc); app.init(hwnd, rc.right-rc.left, rc.bottom-rc.top);

    LARGE_INTEGER f; QueryPerformanceFrequency(&f); LARGE_INTEGER prev; QueryPerformanceCounter(&prev);
    MSG msg{}; bool running=true; while(running){
        while(PeekMessageW(&msg,nullptr,0,0,PM_REMOVE)){ if(msg.message==WM_QUIT){ running=false; break; } TranslateMessage(&msg); DispatchMessageW(&msg);} 
        LARGE_INTEGER now; QueryPerformanceCounter(&now); double dt = double(now.QuadPart - prev.QuadPart)/double(f.QuadPart); prev=now; if(dt>0.05) dt=0.05; app.update(dt); app.render(); Sleep(1);
    }
    return 0;
}